package com.grp6.game.controller;

import com.grp6.game.common.InvalidMoveException;
import com.grp6.game.gameactions.IMove;
import com.grp6.game.model.IGameModel;
import com.grp6.game.player.IPlayer;

/**
 * This class represents the lifecycle of the game.
 * While the game is not finished, game lifecycle validates the player's move <br/>
 * and execute the move otherwise exception is thrown.
 * in this method until the game is finished 
 * @author Group6
 */
public abstract class AbstractGameLifecycle implements IGameLifecycle {
	protected final IGameModel model;
	protected AbstractGameLifecycle(IGameModel model){
		this.model = model;
	}
	
	/**
	 * This method represents the game lifecycle.
	 * Moves made by each player are validated and executed.
	 * The Game stops when a hasGameFinished flag is set.
	 *  
	 */
	public final void runLifecycle(){ // this is the template method
		boolean finished = false;
		do{
			IPlayer player = getNextPlayer();
			try{
				IMove move = player.getNextMove();
				validate(move);
				execute(move);
				finished = hasGameFinished();
			}catch(InvalidMoveException e){
				model.notifyInvalidMove(e);
			}
		} while(!finished);
	}
	
	/**
	 * This method indicates whether the game has finished
	 * @return flag to indicate end of game
	 */
	protected abstract boolean hasGameFinished();
	
	/**
	 * This method executes a valid move made by the player.
	 * The execution logic is to be implemented by the game developer
	 * @param move
	 */
	protected abstract void execute(IMove move);
	
	/**
	 * This method validates the move made by the player.
	 * The rules for validation are implemented by game developer
	 * @param move
	 * @throws InvalidMoveException
	 */
	protected abstract void validate(IMove move) throws InvalidMoveException;
	
	/**
	 * This method gets the player who had made the move.
	 * @return
	 */
	protected abstract IPlayer getNextPlayer();
}
